<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
	</head>
	<body></body>
	<script>
		new Promise((resolve, reject) => {
			//1 首先先定义一个对象， 有个自执行器函数，创建对像时就会自动执行此方法
			//2 promise 三个状态，1 pending 等待 2 fulfilled 成功3 rejected 失败
			//3 状态的改变 3.1  pending->fulfilled  3.2 pending->reject
			//4 resolve函数代表成功， reject 函数代表失败。执行任何一个方法都不会再执行另一个方法（即：状态改变就不能进行修改）
			//5 根据第四点定义一个变量 来管控状态
			//6

			resolve(1)
			reject('error')
		})
			.then(
				(res) => {
					//6 then方法是有两个回调函数，第一个代表resolve成功后的回调，第二个代表rejected失败后的回调
					//6.1 then 方法的 返回值  的类型可能为普通类型，可能为promise 类型
					//6.1.1 then方法 可能不会传递回调函数
					//6.2 promise 可以有多个then方法，需要在此方法中返回promise,来完成链式调用
					//6.3 then方法的返回值不能为自己的promise，否自会无线循环
					//由于存在异步的原因，先把回调函数存储取来，等resolve or reject 执行完，再进行处理
				},
				(err) => {}
			)
			.then(
				(res) => {
					// 6.4 有多个then 的情况，会依次执行，所以要在then方法中存储
				},
				(err) => {}
			)
			.finally(() => {
				//10:无论Promise的对象是成功还是失败，都会执行此方法
				//10.1 返回promise对象，实现链式调用
				//10.2 此函数可能会执行到异步函数。所以用promise 包裹一层。promise.resolve(callback()).then(返回结果)
			})
			.catch((error) => {
				// 7 定义catch 方法，实质就是then方法中rejected
				console.log(error)
			})
		Promise.all(['a', 'n', 'c']).then((res) => {
			//8.1 res 是一个从按照数组顺序返回的结果，[a,b,c]
			//8.2此方法是个静态方法
			//8.3 值的注意的是由于可能因为异步的原因，结果不能按照位置存取
			//8.3.1 判断数组中的元素是普通类型还是promise类
			//8.4 返回值是一个promise
		})
		Promise.resolve(1)
		//9 静态， 判断参数是普通值还是promise ,并且返回promise类型

		const PENDING = 'pending'
		const FULFILLED = 'fulfilled'
		const REJECTED = 'rejected'
		class MyPromise {
			constructor(executor) {
				try {
					executor(this.resolve, this.reject)
				} catch (error) {
					this.reject(error)
				}
			}
			status = PENDING
			value = undefined
			error = undefined
			successCallback = []
			failCallback = []
			resolve = (data) => {
				if (this.status === PENDING) {
					this.status = FULFILLED
					this.value = data
					while (this.successCallback.length) {
						this.successCallback.shift()()
					}
				}
			}
			reject = (error) => {
				if (this.status === PENDING) {
					this.status = REJECTED
					this.error = error
					while (this.failCallback.length) {
						this.failCallback.shift()()
					}
				}
			}
			catch = (failCallback) => {
				return this.then(undefined, failCallback)
			}
			then(successCallback, errorCallback) {
				successCallback = successCallback ? successCallback : (v) => v
				errorCallback = errorCallback
					? errorCallback
					: (v) => {
							throw v
					  }
				let promise2 = new MyPromise((resolve, reject) => {
					if (this.status === FULFILLED) {
						//成功的回调
						//异步执行，得到promise2
						try {
							setTimeout(() => {
								let x = successCallback(this.value)
								console.log('promise2已经获取了')
								resolvePromise(promise2, x, resolve, reject)
							}, 0)
						} catch (error) {
							reject(error)
						}
					} else if (this.status === REJECTED) {
						//失败后的回调
						try {
							//异步执行，得到promise2
							setTimeout(() => {
								console.log('promise2已经获取了')
								let x = errorCallback(this.error)
								resolvePromise(promise2, x, resolve, reject)
							}, 0)
						} catch (error) {
							reject(error)
						}
					} else {
						//由于异步原因 ，状态还处于等待状态
						console.log('异步处理')
						this.successCallback.push(() => {
							setTimeout(() => {
								try {
									let x = successCallback(this.value)
									resolvePromise(promise2, x, resolve, reject)
								} catch (error) {
									reject(error)
								}
							}, 0)
						})
						this.failCallback.push(() => {
							setTimeout(() => {
								try {
									let x = errorCallback(this.value)
									resolvePromise(promise2, x, resolve, reject)
								} catch (error) {
									reject(error)
								}
							}, 0)
						})
					}
				})
				return promise2
			}

			static all(array) {
				let result = []
				let index = 0
				return new MyPromise((resolve, reject) => {
					function addData(key, value) {
						result[key] = value
						index++
						if (index === array.length) {
							resolve(result)
						}
					}
					for (let i = 0; i < array.length; i++) {
						let cur = array[i]
						if (cur instanceof MyPromise) {
							cur.then(
								(res) => addData(i, res),
								(err) => reject(err)
							)
						} else {
							addData(i, cur)
						}
					}
				})
			}
			static resolve(value) {
				if (value instanceof MyPromise) return value
				return new Promise((resolve) => resolve(value))
			}
			finally(callback) {
				return this.then(
					(value) => {
						return MyPromise.resolve(callback()).then(() => value)
					},
					(err) => {
						return MyPromise.resolve(callback()).then(() => {
							throw err
						})
					}
				)
			}
		}
		function resolvePromise(p2, x, resolve, reject) {
			if (p2 === x) {
				console.log('循环调用x')
				return reject(
					new TypeError(
						'Chaining cycle detected for promise #<Promise>'
					)
				)
			}
			if (x instanceof MyPromise) {
				console.log('新的then')
				x.then(resolve, reject)
			} else {
				console.log('新的值')
				console.log(x)
				resolve(x)
			}
		}
		function other() {
			return new MyPromise((resolve, reject) => {
				setTimeout(() => {
					resolve('other1')
				}, 100)
			})
		}
		function other2() {
			return new MyPromise((resolve, reject) => {
				setTimeout(() => {
					resolve('other1')
				}, 200)
			})
		}
		MyPromise.all(['a', 'b', other(), other2(), 'c'])
			.then((res) => {
				console.log('all 得到的结果')
				console.log(res)
			})
			.finally((res) => {
				console.log('finally')
				console.log(res)
				console.log('执行了了呢')
				return 11
			})
			.then((res) => {
				console.log('finally then' + res)
			})
	</script>
</html>
